﻿using Frameworks;
using Network.Core;
using Network.Core.RPC;
using Network.General;
using Network.General.Client;
using UnityEngine;

namespace Client
{
    public class OnlineManager : Singleton<OnlineManager>
    {
        private string _host = "127.0.0.1";
        private int _port = 5152;
        private bool _connected = false;

        public bool IsHost { set; get; }

        public NetManager Net { get { return _net; } }
        private NetManager _net = null;

        public UserData MainUserData { get { return _mainUserData; } }
        private UserData _mainUserData = null; // self

        private HeartBeatHandler _heartbeat;

        private OnlineManager() { }

        public override void OnSingletonInit()
        {
            base.OnSingletonInit();

            Init();
        }

        public override void Dispose()
        {
            Net.Clean();

            GameManager.Instance?.RemoveFixedUpdateListener(onUpdate);
            _heartbeat.onTimeout -= OnHeartBeatTimeout;

            base.Dispose();
        }

        public void Init()
        {
            _net = new NetManager();
            _net.Init(ConnectionType.UDP, 0);
            _net.Rpc.RegisterListener(this);

            GameManager.Instance.AddUpdateListener(onUpdate);

            _heartbeat = new HeartBeatHandler();
            _heartbeat.Init(_net);
            _heartbeat.onTimeout += OnHeartBeatTimeout;
        }

        private void onUpdate()
        {
            _net.Tick();
        }

        private void OnHeartBeatTimeout()
        {
            Debug.LogWarning("Client.OnlineManager.OnHeartBeatTimeout");

            CloseConnect();
            _heartbeat.Stop();

            // 执行断线重连策略

            ReLogin();
        }

        public void Connect()
        {
            if (!_connected)
            {
                _net.Connect(_host, _port);
                _connected = _net.IsConnected;
            }
        }

        private void CloseConnect()
        {
            _net.Close();
            _connected = false;
        }

        public void Login(string host, int port, string account)
        {
            _host = host;
            _port = port;

            Connect();

            LoginReq request = new LoginReq();
            request.id = 0;
            request.account = account;
            _net.Send<LoginRsp>(ProtoCmd.LoginReq, request, onLoginResponse, 30, onLoginError);
        }

        private void ReLogin()
        {
            Connect();

            LoginReq request = new LoginReq();
            request.id = (int)_mainUserData.id;
            request.account = _mainUserData.account;
            _net.Send<LoginRsp>(ProtoCmd.LoginReq, request, onLoginResponse, 30, onLoginError);
        }

        private void onLoginResponse(uint index, LoginRsp response)
        {
            Debug.Log("登录服务器成功,SessionID=" + response.userdata.id);

            if (response.ret.code == 0)
            {
                _mainUserData = response.userdata;

                _heartbeat.Start();

                // 建权
                _net.SetToken(response.userdata.id);
                //_net.Rpc.RegisterListener(this);

                EventProxy.BroadcastEvent(LobbyEvent.LoginSuccess, _mainUserData);
            }
            else
            {
                Debug.LogWarning(response.ret.info);
            }
        }

        private void onLoginError(NetErrorCode errcode)
        {
            Debug.Log("登录错误 Error Code " + errcode);
        }

        public void Logout()
        {
            _heartbeat.Stop();

            if (_mainUserData != null)
            {
                _net.Rpc.Invoke("Logout");
            }
            _mainUserData = null;
        }

        [RPCResponse]
        private void OnLogout()
        {
            _connected = false;
        }
    }
}